#!/bin/bash
#
# CP2K (GNU) arch file for a serial static x86_64 binary
#
# Tested with: GNU 14.2.0
#
# Usage: Source this arch file and then run make as instructed.
#
# Last update: 12.06.2025
#
# \
   if [[ "${0}" == "${BASH_SOURCE}" ]]; then \
      echo "ERROR: Script ${0##*/} must be sourced"; \
      echo "Usage: source ${0##*/}"; \
      exit 1; \
   fi; \
   this_file=${BASH_SOURCE##*/}; \
   cd tools/toolchain; \
   rm -rf build; \
   [[ -z "${target_cpu}" ]] && target_cpu="native"; \
   echo "Found GCC $(gcc -dumpfullversion) compiler"; \
   ./install_cp2k_toolchain.sh -j${maxtasks} --mpi-mode=no --no-arch-files --target-cpu=${target_cpu} --with-gcc \
                                             --with-ace --with-dftd4 --with-hdf5 --with-tblite --with-trexio; \
   source ./install/setup; \
   cd ../..; \
   echo; \
   echo "Check the output above for error messages and consistency!"; \
   echo; \
   echo "If everything is OK, you can build a CP2K production binary with"; \
   echo "   make -j ARCH=${this_file%.*} VERSION=${this_file##*.} TARGET_CPU=${target_cpu}"; \
   echo "Further checks are performed, if DO_CHECKS=yes is added, but this disables static linking."; \
   echo; \
   return

# Set options
DO_CHECKS      := no
TARGET_CPU     := native

# Retrieve package versions
GNU_VER        := $(shell gcc -dumpfullversion)
USE_ACE        := $(ACE_VER)
USE_DFTD4      := $(DFTD4_VER)
USE_FFTW       := $(FFTW_VER)
USE_HDF5       := $(HDF5_VER)
USE_LIBGRPP    := install
USE_LIBINT     := $(LIBINT_VER)
USE_LIBVORI    := $(LIBVORI_VER)
USE_LIBXC      := $(LIBXC_VER)
USE_LIBXSMM    := $(LIBXSMM_VER)
USE_OPENBLAS   := $(OPENBLAS_VER)
USE_SPGLIB     := $(SPGLIB_VER)
USE_TBLITE     := $(TBLITE_VER)
USE_TREXIO     := $(TREXIO_VER)

LMAX           := 5
MAX_CONTR      := 4

CC             := gcc
CXX            := g++
FC             := gfortran
LD             := gfortran
AR             := ar -r

ifeq ($(TARGET_CPU), generic)
   CFLAGS         := -O2 -fopenmp -fopenmp-simd -ftree-vectorize -funroll-loops -g -mtune=$(TARGET_CPU)
else
   CFLAGS         := -O2 -fopenmp -fopenmp-simd -ftree-vectorize -funroll-loops -g -march=$(TARGET_CPU) -mtune=$(TARGET_CPU)
endif

DFLAGS         += -D__MAX_CONTR=$(strip $(MAX_CONTR))

INSTALL_PATH   := $(PWD)/tools/toolchain/install

# Settings for regression testing
ifeq ($(DO_CHECKS), yes)
   DFLAGS         += -D__CHECK_DIAG
#  CFLAGS_DEBUG   := -fsanitize=address
   CFLAGS_DEBUG   := -fsanitize=leak
   FCFLAGS_DEBUG  := -fcheck=bounds,do,recursion,pointer
   FCFLAGS_DEBUG  += -fcheck=all,no-array-temps
   FCFLAGS_DEBUG  += -ffpe-trap=invalid,overflow,zero
   FCFLAGS_DEBUG  += -fimplicit-none
   FCFLAGS_DEBUG  += -finit-derived
   FCFLAGS_DEBUG  += -finit-real=snan
   FCFLAGS_DEBUG  += -finit-integer=-42
   FCFLAGS_DEBUG  += -finline-matmul-limit=0
   WFLAGS         := -Werror=aliasing
   WFLAGS         += -Werror=ampersand
   WFLAGS         += -Werror=c-binding-type
   WFLAGS         += -Werror=conversion
   WFLAGS         += -Werror=intrinsic-shadow
   WFLAGS         += -Werror=intrinsics-std
   WFLAGS         += -Werror=line-truncation
   WFLAGS         += -Wrealloc-lhs
   WFLAGS         += -Werror=tabs
   WFLAGS         += -Werror=target-lifetime
   WFLAGS         += -Werror=underflow
   WFLAGS         += -Werror=unused-but-set-variable
   WFLAGS         += -Werror=unused-dummy-argument
   WFLAGS         += -Werror=unused-variable
endif

ifneq ($(USE_LIBVORI),)
   USE_LIBVORI    := $(strip $(USE_LIBVORI))
   LIBVORI_LIB    := $(INSTALL_PATH)/libvori-$(USE_LIBVORI)/lib
   DFLAGS         += -D__LIBVORI
   LIBS           += $(LIBVORI_LIB)/libvori.a
endif

ifneq ($(USE_LIBXC),)
   USE_LIBXC      := $(strip $(USE_LIBXC))
   LIBXC_INC      := $(INSTALL_PATH)/libxc-$(USE_LIBXC)/include
   LIBXC_LIB      := $(INSTALL_PATH)/libxc-$(USE_LIBXC)/lib
   CFLAGS         += -I$(LIBXC_INC)
   DFLAGS         += -D__LIBXC
   LIBS           += $(LIBXC_LIB)/libxcf03.a
   LIBS           += $(LIBXC_LIB)/libxc.a
endif

ifeq ($(USE_TBLITE),)
  ifneq ($(USE_DFTD4),)
     USE_DFTD4      := $(strip $(USE_DFTD4))
     DFTD4_INC      := $(INSTALL_PATH)/dftd4-$(USE_DFTD4)/include
     DFTD4_LIB      := $(INSTALL_PATH)/dftd4-$(USE_DFTD4)/lib
     CFLAGS         += -I$(DFTD4_INC)/dftd4/GNU-$(GNU_VER)
     DFLAGS         += -D__DFTD4
     LIBS           += $(DFTD4_LIB)/libdftd4.a
     LIBS           += $(DFTD4_LIB)/libmstore.a
     LIBS           += $(DFTD4_LIB)/libmulticharge.a
     LIBS           += $(DFTD4_LIB)/libmctc-lib.a
  endif
endif

ifneq ($(USE_LIBGRPP),)
   USE_LIBGRPP    := $(strip $(USE_LIBGRPP))
   DFLAGS         += -D__LIBGRPP
endif

ifneq ($(USE_LIBINT),)
   USE_LIBINT     := $(strip $(USE_LIBINT))
   LMAX           := $(strip $(LMAX))
   LIBINT_INC     := $(INSTALL_PATH)/libint-v$(USE_LIBINT)-cp2k-lmax-$(LMAX)/include
   LIBINT_LIB     := $(INSTALL_PATH)/libint-v$(USE_LIBINT)-cp2k-lmax-$(LMAX)/lib
   CFLAGS         += -I$(LIBINT_INC)
   DFLAGS         += -D__LIBINT
   LIBS           += $(LIBINT_LIB)/libint2.a
endif

ifneq ($(USE_SPGLIB),)
   USE_SPGLIB     := $(strip $(USE_SPGLIB))
   SPGLIB_INC     := $(INSTALL_PATH)/spglib-$(USE_SPGLIB)/include
   SPGLIB_LIB     := $(INSTALL_PATH)/spglib-$(USE_SPGLIB)/lib
   CFLAGS         += -I$(SPGLIB_INC)
   DFLAGS         += -D__SPGLIB
   LIBS           += $(SPGLIB_LIB)/libsymspg.a
endif

ifneq ($(USE_LIBXSMM),)
   USE_LIBXSMM    := $(strip $(USE_LIBXSMM))
   LIBXSMM_INC    := $(INSTALL_PATH)/libxsmm-$(USE_LIBXSMM)/include
   LIBXSMM_LIB    := $(INSTALL_PATH)/libxsmm-$(USE_LIBXSMM)/lib
   CFLAGS         += -I$(LIBXSMM_INC)
   DFLAGS         += -D__LIBXSMM
   LIBS           += $(LIBXSMM_LIB)/libxsmmf.a
   LIBS           += $(LIBXSMM_LIB)/libxsmmext.a
   LIBS           += $(LIBXSMM_LIB)/libxsmm.a
endif

ifneq ($(USE_ACE),)
   USE_ACE        := $(strip $(USE_ACE))
   ACE_INC        := $(INSTALL_PATH)/lammps-user-pace-$(USE_ACE)/include
   ACE_LIB        := $(INSTALL_PATH)/lammps-user-pace-$(USE_ACE)/lib
   CFLAGS         += -I$(ACE_INC)
   DFLAGS         += -D__ACE
   LIBS           += $(ACE_LIB)/libpace.a
   LIBS           += $(ACE_LIB)/libyaml-cpp-pace.a
   LIBS           += $(ACE_LIB)/libcnpy.a
endif

ifneq ($(USE_FFTW),)
   USE_FFTW       := $(strip $(USE_FFTW))
   FFTW_INC       := $(INSTALL_PATH)/fftw-$(USE_FFTW)/include
   FFTW_LIB       := $(INSTALL_PATH)/fftw-$(USE_FFTW)/lib
   CFLAGS         += -I$(FFTW_INC)
   DFLAGS         += -D__FFTW3
   LIBS           += $(FFTW_LIB)/libfftw3_omp.a
   LIBS           += $(FFTW_LIB)/libfftw3.a
endif

ifneq ($(USE_OPENBLAS),)
   USE_OPENBLAS   := $(strip $(USE_OPENBLAS))
   OPENBLAS_INC   := $(INSTALL_PATH)/openblas-$(USE_OPENBLAS)/include
   OPENBLAS_LIB   := $(INSTALL_PATH)/openblas-$(USE_OPENBLAS)/lib
   CFLAGS         += -I$(OPENBLAS_INC)
   LIBS           += $(OPENBLAS_LIB)/libopenblas.a
endif

ifneq ($(USE_TREXIO),)
   USE_TREXIO     := $(strip $(USE_TREXIO))
   TREXIO_INC     := $(INSTALL_PATH)/trexio-$(USE_TREXIO)/include
   TREXIO_LIB     := $(INSTALL_PATH)/trexio-$(USE_TREXIO)/lib
   CFLAGS         += -I$(TREXIO_INC)
   DFLAGS         += -D__TREXIO
   LIBS           += $(TREXIO_LIB)/libtrexio.a
endif

ifneq ($(USE_TBLITE),)
   USE_TBLITE     := $(strip $(USE_TBLITE))
   TBLITE_INC     := $(INSTALL_PATH)/tblite-$(USE_TBLITE)/include
   TBLITE_LIB     := $(INSTALL_PATH)/tblite-$(USE_TBLITE)/lib
   CFLAGS         += -I$(TBLITE_INC)/toml-f/modules
   CFLAGS         += -I$(TBLITE_INC)/mctc-lib/modules
   CFLAGS         += -I$(TBLITE_INC)/s-dftd3/GNU-$(GNU_VER)
   CFLAGS         += -I$(TBLITE_INC)/dftd4/GNU-$(GNU_VER)
   CFLAGS         += -I$(TBLITE_INC)/tblite/GNU-$(GNU_VER)
   DFLAGS         += -D__TBLITE
   DFLAGS         += -D__DFTD4
   LIBS           += $(TBLITE_LIB)/libtblite.a
   LIBS           += $(TBLITE_LIB)/libdftd4.a
   LIBS           += $(TBLITE_LIB)/libs-dftd3.a
   LIBS           += $(TBLITE_LIB)/libmulticharge.a
   LIBS           += $(TBLITE_LIB)/libmctc-lib.a
   LIBS           += $(TBLITE_LIB)/libtoml-f.a
endif

ifneq ($(USE_HDF5),)
   USE_HDF5       := $(strip $(USE_HDF5))
   HDF5_INC       := $(INSTALL_PATH)/hdf5-$(USE_HDF5)/include
   HDF5_LIB       := $(INSTALL_PATH)/hdf5-$(USE_HDF5)/lib
   CFLAGS         += -I$(HDF5_INC)
   DFLAGS         += -D__HDF5
   LIBS           += $(HDF5_LIB)/libhdf5_fortran.a
   LIBS           += $(HDF5_LIB)/libhdf5_f90cstub.a
   LIBS           += $(HDF5_LIB)/libhdf5.a
   LIBS           += -lz
endif

CFLAGS         += $(DFLAGS) $(CFLAGS_DEBUG)

CXXFLAGS       := $(CFLAGS)

FCFLAGS        := $(CFLAGS) $(FCFLAGS_DEBUG) $(WFLAGS)
ifeq ($(shell [ $(shell gcc -dumpversion | cut -d. -f1) -gt 9 ] && echo yes), yes)
   FCFLAGS        += -fallow-argument-mismatch
endif
FCFLAGS        += -fbacktrace
FCFLAGS        += -ffree-form
FCFLAGS        += -ffree-line-length-none
FCFLAGS        += -fno-omit-frame-pointer
FCFLAGS        += -std=f2008

CFLAGS         += -std=c17
CXXFLAGS       += -std=c++17

# The LeakSanitizer does not work with static linking
ifeq ($(DO_CHECKS), yes)
   LDFLAGS        += $(FCFLAGS)
else
   LDFLAGS        += $(FCFLAGS) -static
endif

LIBS           += -Wl,--whole-archive -lpthread -ldl -Wl,--no-whole-archive -lstdc++

# End
